package com.game.framework.orm.jdbc;

import java.lang.reflect.*;
import java.sql.*;
import java.util.*;

import com.game.utils.log.Log;


/**
 * ConnectionPoolProxyImpl: 连接池实现2<br>
 * 说明：该类测试有些问题，暂不使用。<br>
 * @author Liyuan
 */
public class ConnectionPoolProxyImpl implements ConnectionPool {
	private Integer minSize 		= 1;
	private Integer maxSize 		= 3;
	private String	url 			= null;
	
	/** connectionProvider */
	private ConnectionProvider connectionProvider = null;
	/** connectionPool */
	private List<Connection> connectionPool = new ArrayList<Connection>();
	
	
	/** 构造函数 */
	public ConnectionPoolProxyImpl(Integer minSize, Integer maxSize, String url) {
		this.minSize = minSize;
		this.maxSize = maxSize;
		this.url 	= url;
		this.init();
	}
	
	//公共接口
	/**
	 * 从连接池取出连接
	 * @return
	 * @throws SQLException
	 */
	public Connection getConnection() throws SQLException {
		Connection connection = null;
		synchronized (connectionPool) {
			if (!connectionPool.isEmpty()) {
				connection = connectionPool.remove(connectionPool.size() - 1);
				return getProxy(connection, this);
			}
		}
		connection = connectionProvider.getConnection();
		return getProxy(connection, this);
	}
	
	/**
	 * 释放连接到连接池
	 * @param conn
	 * @throws SQLException
	 */
	public void releaseConnection(Connection connection) throws SQLException {
		synchronized (connectionPool) {
			int currentSize = connectionPool.size();
			if (currentSize < maxSize) {
				connectionPool.add(connection);
				return;
			}
		}
		closeJdbcConnection(connection);
	}
	
	/**
	 * 关闭连接池
	 */
	public void close() {
		Iterator<Connection> iterator = connectionPool.iterator();
		while (iterator.hasNext()) {
			try {
				closeJdbcConnection(iterator.next());
			} catch (SQLException e) {
				Log.printStackTrace(e);
			}
		}
		connectionPool.clear();
	}
	
	
	//私有方法
	/**
	 * 初始化连接池
	 */
	private void init(){
		try {
			if(url == null || "".equals(url)) return;
			connectionProvider 	= new ConnectionProvider(this.url);
			connectionPool		= new ArrayList<Connection>();
			for(int i=0; i < minSize; ++i){
				connectionPool.add(connectionProvider.getConnection());
			}
		} catch (Exception e) {
			Log.printStackTrace(e);
		}
	}
	
	/**
	 * closeJdbcConnection
	 * @param connection
	 * @throws SQLException
	 */
	private void closeJdbcConnection(Connection connection) throws SQLException {
		ConnectionProxy connectionProxy = (ConnectionProxy) connection;
		connectionProxy.getJdbcConnection().close();
	}
	
	/**
	 * getProxy
	 * @param connection
	 * @param connectionPool
	 * @return
	 */
	private Connection getProxy(final Connection connection, final ConnectionPool connectionPool) {
		InvocationHandler handler = new InvocationHandler() {
			public Object invoke(Object proxy, Method method, Object args[])
					throws Exception {
				if (method.getName().equals("close")) {
					connectionPool.releaseConnection((Connection) proxy);
					return null;
				} else if (method.getName().equals("getJdbcConnection")) {
					return connectionPool;
				} else {
					return method.invoke(connectionPool, args);
				}
			}
		};

		return (Connection) Proxy.newProxyInstance(ConnectionProxy.class
				.getClassLoader(), new Class[] { ConnectionProxy.class }, handler);
	}
	
	/** finalize */
	protected void finalize() {
		close();
	}
	
	/** size */
	public Integer size(){
		return connectionPool == null ? 0 : connectionPool.size(); 
	}
	
}

/** ConnectionProxy */
interface ConnectionProxy extends Connection {
	/** getJdbcConnection */
	public Connection getJdbcConnection();
}


